#include "chainedlist.h"

#include <stdio.h>
#include <malloc.h>

#include "../log/log.h"

CLNode_s* CL_create( void ) 
{
 
  CLNode_s* root;

  // Allocate the root element
  if( !(root = malloc(sizeof(CLNode_s))) )
  {
    LOG_add(LOG_ERROR, CHLIST"malloc failed in %s at %s.",
                __func__,__LINE__);
    return NULL;
  }

  root->prev = NULL;
  root->next = NULL;

  root->data = NULL;

  return root;
}

void CL_destroy(CLNode_s* root)
{
 
  CLNode_s* node = root;//CL_first(root);
  CLNode_s* pnode;

  // If the list is void there is nothing
  // to remove.
  if(!root) return;
  
  while( node )
  {
    pnode = node;
    node = node->next;

    free(pnode);
  }

 // root->next = NULL;

  return;
}

CLNode_s* CL_first(CLNode_s* root)
{
  if(!root) return NULL;

  return (root->next);
}

void CL_map(CLNode_s* root, void(*func)(void*))
{
  if(!root)
    return;
 
  if(!CL_first(root)) return;

  CLNode_s* node;

  for(node=CL_first(root);node;node=node->next)
    func(node->data);

  return;
}

CLNode_s* CL_push(CLNode_s* root, void* data)
{
  CLNode_s* node;
  
  if( !(node = malloc(sizeof(CLNode_s))) )
  { 
    LOG_add(LOG_ERROR, CHLIST"malloc failed in %s at %s.",
                __func__,__LINE__);

    return NULL;
  }
  
  if( root->next )
  {
    // knitting
    node->prev = root;
    node->next = root->next;
    root->next->prev = node;
    root->next = node;
  }
  else
  {
    root->next = node;
    node->prev = root;
    node->next = NULL;
  }

  node->data = data;

  return node;
}

CLNode_s* CL_push_back(CLNode_s* root, void* data)
{
  CLNode_s* node;
  CLNode_s* new;
 
  if(!root) return NULL;

  if( !(new = malloc(sizeof(CLNode_s))) )
  { 
    LOG_add(LOG_ERROR, CHLIST"malloc failed in %s at %s.",
                __func__,__LINE__);

    return NULL;
  }

  for(node = root; node->next; node= node->next);
  
  node->next = new;
  new->prev = node;
  new->next = NULL;

  new->data = data;

  return node;
}

void CL_remove(CLNode_s* node)
{
  // knitting again

  if( node->prev )
    node->prev->next = node->next;
  
  if( node->next )
    node->next->prev = node->prev;

  free(node);

  return;
}

CLNode_s* CL_search_data( CLNode_s* root, void* data )
{
  if(!root)
    return NULL;

  CLNode_s* node;

  for( node=root->next; node; node = node->next )
    if( node->data == data )
      return node;

  return NULL;
}

CLNode_s* CL_search_user(CLNode_s* root,
                        char(*test)(void*,void*),
                        void* value )
{
  if(!root)
    return NULL;

  CLNode_s* node;

  for( node=root->next; node; node = node->next )
    if( test(node->data, value) )
      return node;

  return NULL;
}
